#!/usr/bin/python3
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: t -*-

import os
import re
import sys
import signal
import logging
import pathlib
from gi.repository import GLib
sys.path.append('/usr/lib64/bnetd')
from bnet_util import Util
from bnet_param import WrtConst
from bnet_plugin import WrtPluginHub
from bnet_prefix_pool import PrefixPool


class AgentDaemon:

    def __init__(self, parentNsName, nsName, logLevel):
        assert "-" not in parentNsName
        assert re.fullmatch("[0-9]+-.*", nsName)

        self._parentNsName = parentNsName
        self._nsName = nsName
        self._logLevel = logLevel

        self.runDir = os.path.join(WrtConst.runDir, "ns-%s" % (self._nsName))
        self.varDir = os.path.join(WrtConst.varDir, "ns-%s" % (self._nsName))
        self.logDir = os.path.join(WrtConst.logDir, "ns-%s" % (self._nsName))

    def run(self):
        Util.mkDirAndClear(self.runDir)
        os.makedirs(self.varDir, exist_ok=True)
        os.makedirs(self.logDir, exist_ok=True)
        try:
            logging.getLogger().addHandler(logging.StreamHandler(sys.stderr))
            logging.getLogger().setLevel(self._logLevel)
            logging.info('Manager for bnetd-agent "%s" begins.' % (self._nsName))

            # write pid file
            with open(os.path.join(self.runDir, "bnet-agent.pid"), "w") as f:
                f.write(str(os.getpid()))

            # create main loop
            self.mainloop = GLib.MainLoop()

            # load plugin hub
            self.pluginHub = WrtPluginHub(self)
            logging.info("Plugin HUB loaded.")

            # load prefix pool
            self.prefixPool = PrefixPool(os.path.join(self.varDir, "prefix-pool.json"))
            logging.info("Prefix pool loaded.")

            # business initialize
            # self.uplinkManager = UpconnManager(self.pluginHub, self.prefixPool, self.mntNs, self.netNs, self)
            # self.subnetManagerL2 = SubnetManagerL2(self.pluginHub, self.prefixPool, self.mntNs, self.netNs, self)
            # self.subnetManagerL3 = SubnetManagerL3(self.pluginHub, self.prefixPool, self.mntNs, self.netNs, self)

            # enable ip forward
            assert pathlib.Path(WrtConst.procIpForwareFile).read_text() == "0\n"
            pathlib.Path(WrtConst.procIpForwareFile).write_text("1")
            logging.info("IP forwarding enabled.")

            # start main loop
            logging.info("Mainloop begins.")
            GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGINT, self._sigHandlerINT, None)
            GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGTERM, self._sigHandlerTERM, None)
            GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGHUP, self._sigHandlerHUP, None)
            self.mainloop.run()
            logging.info("Mainloop exits.")
        finally:
            if self.subnetManagerL3 is not None:
                self.subnetManagerL3.dispose()
                self.subnetManagerL3 = None
            if self.subnetManagerL2 is not None:
                self.subnetManagerL2.dispose()
                self.subnetManagerL2 = None
            if self.obConnManager is not None:
                self.obConnManager.dispose()
                self.obConnManager = None
            if self.trafficManager is not None:
                self.trafficManager.dispose()
                self.trafficManager = None
            logging.shutdown()

    def _sigHandlerINT(self, signum):
        logging.info("SIGINT received.")
        self.mainloop.quit()
        return True

    def _sigHandlerTERM(self, signum):
        logging.info("SIGTERM received.")
        self.mainloop.quit()
        return True


parentNsName = sys.argv[0]
nsName = sys.argv[1]
logLevel = Util.getLoggingLevel(sys.argv[3])

# start server
AgentDaemon(parentNsName, nsName, logLevel).run()
